/*
 *  expression_evaluation.c
 *  
 *
 *  Created by Yi Lin on 11-5-7.
 *  Copyright 2011 __MyCompanyName__. All rights reserved.
 *
 */



/* expression evaluation and type inferences */
struct x_evaluation {
        int ret;
        struct t_type type;
        int value;
        
        void *address;
};

struct x_evaluation INVALID_EVALUTION = {-1, default_value, NULL, NULL};
struct x_evaluation DEFAULT_EVALUTION = {};

/* evaluate a common expression */
struct x_evaluation *evaluate_expression(struct x_expression *expression, struct t_type *type) {
        
        switch (expression->cate) {
                case X_UNARY:
                        return evaluate_unary_expression
                                (expression->spec.unary.oper, expression->spec.unary.opnd);
                        
                case X_BINARY:
                        return evaluate_binary_expression
                                (expression->spec.binary.oper, 
                                 expression->spec.unary.left, expression->spec.unary.right);
                        
                case X_TRINARY:
                        return evaluate_trinary_expression
                                (expression->spec.trinary.oper, expression->spec.trinary.first, 
                                 expression.trinary.second, expression.trinary.third);
                        
                case X_IDENTIFIER:
                        return evaluate_identifier
                                (expression->spec.identifier.identifier);
                
                case X_BOOLEAN:
                        struct x_evaluation ret = DEFAULT_EVALUTION;
                        ret.value = expression->spec.boolean.boolean;
                        return ret;
                        
                case X_INTEGER:
                        struct x_evaluation ret = DEFAULT_EVALUTION;
                        ret.value = expression->spec.integer.integer;
                        return ret;
                        
                case X_CALL:
                        return evaluate_function_expression(/* todo */);
                        
                case X_ARRAY:
                        return evaluaate_array_expression
                                (expression->spec.array.array, expression->spec.array.index);
                
                case X_DS:
                        return evaluate_ds_expression(expression->spec.ds);
                        
                default:
                        break;
        }
        
}

struct x_evaluation evaluate_array(char *array, struct x_expression *index){
        
}

struct x_evaluation get_array(char *array){
        return DEFAULT_EVALUTION;
}

struct x_evaluation evaluate_identifier(char *identifier) {
        
        /* get identifier from the access table*/
}

struct x_evaluation evaluate_function
(struct t_type *return_type, struct v_list *arguments, struct s_list *statements, int access_table ) {
        
        if(arguments != NULL)
                append_access_table(access_table, arguments);
        
        struct s_execution execution_ret 
                = execute_statement_list(struct s_list *statements);
        
        
        if (exe_ret == invalid_execution || exe_ret.type != RETURN) {
                
                return INVALID_EVALUATION;
                
        } else 
                return execution_ret.evaluation;
}





void *evaluate_unary_expression
(enum x_unop operator, struct e_expression *operand, struct t_type *type) {
        
}

/* unary operations */
struct x_evaluation not_operation(struct x_evaluation operand){
        
        struct x_evaluation;
        x_evaluation.type.cate = T_BOOLEAN;
        x_evaluation.address = NULL;
        
        switch (operand.type.cate) {
                case T_INTEGER:
                case T_BOOLEAN:
                        x_evaluation = !operand.value;
                        break;
                        
                case T_ENUMERATE:
                        x_evaluation = !operand.value;
                        break;
                        
                default:
                        return INVALID_EVALUTION;
        }
        
}

/* for post-order operation */
struct x_evaluation evaluate_binary_expression
(enum x_unop operator, struct x_expression *left, struct x_expression *right){
        
        struct x_evaluation left_evaluation = evaluate_expression(left);
        struct x_evaluation right_evaluation = evaluate_expression(right);
        
        if (left_evaluation == INVALID_EVALUATION
            || right_evaluation == INVALID_EVALUATION) {
                return INVALID_EVALUATION;
        }
        
        switch (operator) {
                case X_ASSIGN:
                        return assign_operation(left_evaluation, right_evaluation);
                        
                case X_OR:
                case X_AND:
                        return boolean_operation(operator, left_evaluation, right_evaluation);
                        
                case X_EQ:
                case X_NE:
                case X_EQ:
                case X_NE:
                case X_LT:
                case X_LE:
                case X_GT:
                case X_GE:
                        return compare_operation(operator, left_evaluation, right_evaluation);
                        
                case X_ADD:
                case X_SUB:
                case X_MUL:
                case X_DIV:
                case X_MOD:
                        return math_operation(operator, left_evaluation, right_evaluation);
                        
                default:
                        return INVALID_EVALUATION;
                        break;
        }
}

/* value assignment, todo:
        assign value to enumeration.
 */
struct x_evaluation assign_operation
(struct x_evaluation left, struct x_evaluation right) {
        
        if(left.address = NULL)
                return INVALID_EVALUATION;
        
        switch (left.type.t_cate) {
                case T_INTEGER:
                        
                        break;
                
                case T_BOOLEAN
                

                case T_ENUMERATE 
                
                default:
                        break;
        }
}


/* compare_operation happens only among enumeration's values or integers or between*/
struct x_evaluation compare_operation
(enum x_binop compare_operator, struct x_evaluation left, struct x_evaluation right){
 
        struct x_evaluation evaluation;
        evaluation.type.cate = T_BOOLEAN;
        evaluation.address = NULL;
        
        switch (compare_operator) {
                case X_EQ:
                        evaluation.value = (left.value == right.value);
                        break;
                        
                case X_NE:
                        evaluation.value = (left.value != right.value);
                        break;
                
                case X_LT:
                        evaluation.value = (left.value < right.value);
                        break;
                        
                case X_LE:
                        evaluation.value = (left.value <= right.value);
                        break;
                        
                case X_GT:
                        evaluation.value = (left.value > right.value);
                        break;
                        
                case X_GE:
                        evaluation.value = (left.value >= right.value);
                        break;

                default:
                        return INVALID_EVALUATION;
                        break;
        }
        
        return evaluation;
}

struct x_evaluation math_operation
(enum x_binop math_operator, struct x_evaluation left, struct x_evaluation right, int contex) {
        
        if(   (left.type.cate != T_INTEGER && left.type.cate != T_ENUMERATE)
           || (right.type.cate!= T_INTEGER && right.type.cate!= T_ENUMERATE) )
                return INVALID_EVALUATION;
        
        if(contex == INDEX) {
                /* index evaluation. if cate == T_ENUMERATE, return a T_ENUMERATE*/
                return DEFAULT_EVALUTION;
        }
        
        struct x_evaluation ret = DEFAULT_EVALUTION;
        
        ret.type.cate = INTEGER;
        ret.address = NULL;
        
        switch (math_operator) {
                case X_ADD:
                        ret.value = (left.value + right.value);
                        break;
                        
                case X_SUB:
                        ret.value = (left.value - right.value);
                        break;
                        
                case X_MUL:
                        ret.value = (left.value * right.value);
                        break;
                        
                case X_DIV:
                        ret.value = (left.value / right.value);
                        break;
                case X_MOD:
                        ret.value = (left.value % right.value);
                        break;
                        
                default:
                        return INVALID_EVALUATION;
        }
           
        return ret;
}

struct x_evaluation ds_operation (struct ds *ds_struct){
        
        switch (ds->oper) {
                case X_RANDOM:
                        return random_enumeration(ds_struct->spec.random.type);
                        
                case X_VALUE:
                        return evaluate_enumeration(ds_struct->spec.value.enumeration);
                
                case X_SIZE:
                        return container_size_operation(ds_struct->spec.size.container);
                        
                case X_FILL:
                        return container_fill_operation(ds_struct->spec.fill.container);
                        
                case X_SHUFFLE:
                        return container_shuffle_operation(ds_struct->spec.shuffle.container);
                
                case X_PEEK:
                        return container_peek_operation
                        (ds_struct->spec.peek.container, ds_struct->spec.peek.position);
                        
                case X_REMOVE:
                        return container_remove_operation
                        (ds_struct->spec.remove.container, ds_struct->spec.remove.position);
                        
                case X_INSERT:
                        return container_insert_operation
                        (ds_struct->spec.insert.container, ds_struct->spec.insert.position
                         ds_struct->spec.insert.element);
                
                case X_EXTRACT:
                        return container_extract_operation
                        (ds_struct->spec.extract.enumerate, ds_struct->spec.extract.index);
        }

}

struct x_evaluation random_enumeration(struct t_type *type) {

}

struct x_evaluation evaluate_enumeration(struct x_expression *enumeration) {
        struct evaluation ret = evaluate_expression(enumeration);
        
        if (ret.type.cate != T_ENUMERATION) {
                return INVALID_EVALUATION;
        }
        
        return ret;
}

struct x_evaluation container_size_operation(struct x_expression *container) {
        /* get container*/
        
        struct evaluation ret = DEFAULT_EVALUTION;
        ret.type.cate = T_INTEGER;
        ret.value = 1; /*call the function*/
        
        return ret;
}

struct x_evaluation container_fill_operation(struct x_expression *container) {
        
}

struct x_evaluation container_shuflle_operation(struct x_expression *container) {
        
}

struct x_evaluation container_peek_operation
(struct x_expression *container, struct p_position *position) {
        
}

struct x_evaluation container_remove_operation
(struct x_expression *container, struct p_position *position) {
        
}

struct x_evaluation container_insert_operation
(struct x_expression *container, struct p_position *position, struct x_expression *index) {
        
}

struct x_evaluation container_extract_operation
(struct x_expression *enumerate, struct x_expression *index) {
        
}

